﻿using System.Linq;
using System.Web;
using System.Text;
using System.Dynamic;
using System.Collections.Specialized;

namespace Ayatta.Common.Extensions
{
    public static class NameValueCollectionExtension
    {
        public static bool IsTrue(this NameValueCollection collection, string key)
        {
            bool isTrue;

            return collection != null
                && collection.GetValues(key) != null
                && bool.TryParse(collection.GetValues(key)[0], out isTrue)
                && isTrue;
        }

        public static bool? IsTrueNullable(this NameValueCollection form, string key)
        {
            bool? isTrue = null;

            if (form != null && form.GetValues(key) != null)
            {
                bool isTrueValue;

                if (bool.TryParse(form.GetValues(key)[0], out isTrueValue))
                    isTrue = isTrueValue; //FUNNY: (erikpo) Like the hardware store?
            }

            return isTrue;
        }

        public static NameValueCollection Sort(this NameValueCollection nameValue)
        {
            var nv = new NameValueCollection(nameValue.Count);
            var keys = nameValue.AllKeys.ToList();
            keys.Sort();
            foreach (var key in keys)
            {
                nv[key] = nameValue[key];
            }
            return nv;
        }

        public static NameValueCollection Filter(this NameValueCollection nameValue, string[] excludeKeys)
        {
            var keys = nameValue.AllKeys;
            var nv = new NameValueCollection(nameValue.Count);
            foreach (var key in keys.Where(key => !excludeKeys.Contains(key)))
            {
                nv[key] = nameValue[key];
            }
            return nv;
        }

        public static string ToQueryString(this NameValueCollection queryString, bool includeQuestionMark = false,bool skipEmpty=false,bool urlEncode=false)
        {
            if (queryString.Count > 0)
            {
                var qs = new StringBuilder();
                if (includeQuestionMark)
                {
                    qs.Append("?");
                }
                for (var i = 0; i < queryString.Count; i++)
                {
                    if (i > 0)
                    {
                        qs.Append("&");
                    }
                    if (skipEmpty)
                    {
                        if (!string.IsNullOrEmpty(queryString.Keys[i].Trim()))
                        {
                            if (urlEncode)
                            {
                                var val =HttpUtility.UrlEncode(queryString[i].Trim());
                                qs.AppendFormat("{0}={1}", queryString.Keys[i].Trim(),val);
                            }
                            else
                            {
                                qs.AppendFormat("{0}={1}", queryString.Keys[i].Trim(), queryString[i].Trim());
                            }
                        }
                    }
                    else
                    {
                        if (urlEncode)
                        {
                            var val = HttpUtility.UrlEncode(queryString[i].Trim());
                            qs.AppendFormat("{0}={1}", queryString.Keys[i].Trim(), val);
                        }
                        else
                        {
                            qs.AppendFormat("{0}={1}", queryString.Keys[i].Trim(), queryString[i].Trim());
                        }
                    }
                }
                return qs.ToString();
            }
            return string.Empty;
        }


        public static dynamic AsDynamic(this NameValueCollection nameValueCollection, bool replace = false)
        {
            return new DynamicParam(nameValueCollection, replace);
        }
    }

    internal sealed class DynamicParam : DynamicObject
    {
        private readonly NameValueCollection nameValueCollection;
        public NameValueCollection Raw
        {
            get { return nameValueCollection; }
        }
        public DynamicParam(NameValueCollection nameValueCollection, bool replace = false)
        {
            if (replace)
            {
                this.nameValueCollection = new NameValueCollection(nameValueCollection.Count);
                foreach (var o in nameValueCollection.AllKeys)
                {
                    this.nameValueCollection.Add(o.Replace('_', '\0'), nameValueCollection[o]);
                }
            }
            else
            {
                this.nameValueCollection = nameValueCollection;
            }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = nameValueCollection[binder.Name];
            return true;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            nameValueCollection[binder.Name] = value.ToString();
            return true;
        }
    }
}